# encoding: utf-8
class modelGj(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, x):
        x2, (_, l) = self.lstmEncode(x)
        alld = self.linDecode(x2)

        xd = alld[:, :, 0]
        yd = alld[:, :, 1]

        xd = self.sig(xd)
        yd = self.sig(yd)
        return xd, yd


class bezierTrajectory:

    def _bztsg(self, dataTrajectory):
        lengthOfdata = len(dataTrajectory)

        def staer(x):
            t = ((x - dataTrajectory[0][0]) / (dataTrajectory[-1][0] - dataTrajectory[0][0]))
            y = np.array([0, 0], dtype=np.float64)
            for s in range(len(dataTrajectory)):
                y += dataTrajectory[s] * ((math.factorial(lengthOfdata - 1) / (
                        math.factorial(s) * math.factorial(lengthOfdata - 1 - s))) * math.pow(t, s) * math.pow(
                    (1 - t), lengthOfdata - 1 - s))
            return y[1]

        return staer

    def _type(self, type, x, numberList):
        numberListre = []
        pin = (x[1] - x[0]) / numberList
        if type == 0:
            for i in range(numberList):
                numberListre.append(i * pin)
            if pin >= 0:
                numberListre = numberListre[::-1]
        elif type == 1:
            for i in range(numberList):
                numberListre.append(1 * ((i * pin) ** 2))
            numberListre = numberListre[::-1]
        elif type == 2:
            for i in range(numberList):
                numberListre.append(1 * ((i * pin - x[1]) ** 2))

        elif type == 3:
            dataTrajectory = [np.array([0, 0]), np.array([(x[1] - x[0]) * 0.8, (x[1] - x[0]) * 0.6]),
                              np.array([x[1] - x[0], 0])]
            fun = self._bztsg(dataTrajectory)
            numberListre = [0]
            for i in range(1, numberList):
                numberListre.append(fun(i * pin) + numberListre[-1])
            if pin >= 0:
                numberListre = numberListre[::-1]
        numberListre = np.abs(np.array(numberListre) - max(numberListre))
        biaoNumberList = ((numberListre - numberListre[numberListre.argmin()]) / (
                numberListre[numberListre.argmax()] - numberListre[numberListre.argmin()])) * (x[1] - x[0]) + x[0]
        biaoNumberList[0] = x[0]
        biaoNumberList[-1] = x[1]
        return biaoNumberList

    def getFun(self, s):
        '''

        :param s: 传入P点
        :return: 返回公式
        '''
        dataTrajectory = []
        for i in s:
            dataTrajectory.append(np.array(i))
        return self._bztsg(dataTrajectory)

    def simulation(self, start, end, le=1, deviation=0, bias=0.5):
        '''

        :param start:开始点的坐标 如 start = [0, 0]
        :param end:结束点的坐标 如 end = [100, 100]
        :param le:几阶贝塞尔曲线，越大越复杂 如 le = 4
        :param deviation:轨迹上下波动的范围 如 deviation = 10
        :param bias:波动范围的分布位置 如 bias = 0.5
        :return:返回一个字典equation对应该曲线的方程，P对应贝塞尔曲线的影响点
        '''
        start = np.array(start)
        end = np.array(end)
        cbb = []
        if le != 1:
            e = (1 - bias) / (le - 1)
            cbb = [[bias + e * i, bias + e * (i + 1)] for i in range(le - 1)]

        dataTrajectoryList = [start]

        t = random.choice([-1, 1])
        w = 0
        for i in cbb:
            px1 = start[0] + (end[0] - start[0]) * (random.random() * (i[1] - i[0]) + (i[0]))
            p = np.array([px1, self._bztsg([start, end])(px1) + t * deviation])
            dataTrajectoryList.append(p)
            w += 1
            if w >= 2:
                w = 0
                t = -1 * t

        dataTrajectoryList.append(end)
        return {"equation": self._bztsg(dataTrajectoryList), "P": np.array(dataTrajectoryList)}

    def trackArray(self, start, end, numberList, le=1, deviation=0, bias=0.5, type=0, cbb=0, yhh=10):
        '''

        :param start:开始点的坐标 如 start = [0, 0]
        :param end:结束点的坐标 如 end = [100, 100]
        :param numberList:返回的数组的轨迹点的数量 numberList = 150
        :param le:几阶贝塞尔曲线，越大越复杂 如 le = 4
        :param deviation:轨迹上下波动的范围 如 deviation = 10
        :param bias:波动范围的分布位置 如 bias = 0.5
        :param type:0表示均速滑动，1表示先慢后快，2表示先快后慢，3表示先慢中间快后慢 如 type = 1
        :param cbb:在终点来回摆动的次数
        :param yhh:在终点来回摆动的范围
        :return:返回一个字典trackArray对应轨迹数组，P对应贝塞尔曲线的影响点
        '''
        s = []
        fun = self.simulation(start, end, le, deviation, bias)
        w = fun['P']
        fun = fun["equation"]
        if cbb != 0:
            numberListOfcbb = round(numberList * 0.2 / (cbb + 1))
            numberList -= (numberListOfcbb * (cbb + 1))

            xTrackArray = self._type(type, [start[0], end[0]], numberList)
            for i in xTrackArray:
                s.append([i, fun(i)])
            dq = yhh / cbb
            kg = 0
            ends = np.copy(end)
            for i in range(cbb):
                if kg == 0:
                    d = np.array([end[0] + (yhh - dq * i),
                                  ((end[1] - start[1]) / (end[0] - start[0])) * (end[0] + (yhh - dq * i)) + (
                                          end[1] - ((end[1] - start[1]) / (end[0] - start[0])) * end[0])])
                    kg = 1
                else:
                    d = np.array([end[0] - (yhh - dq * i),
                                  ((end[1] - start[1]) / (end[0] - start[0])) * (end[0] - (yhh - dq * i)) + (
                                          end[1] - ((end[1] - start[1]) / (end[0] - start[0])) * end[0])])
                    kg = 0
                y = self.trackArray(ends, d, numberListOfcbb, le=2, deviation=0, bias=0.5, type=0, cbb=0, yhh=10)
                s += list(y['trackArray'])
                ends = d
            y = self.trackArray(ends, end, numberListOfcbb, le=2, deviation=0, bias=0.5, type=0, cbb=0, yhh=10)
            s += list(y['trackArray'])

        else:
            xTrackArray = self._type(type, [start[0], end[0]], numberList)
            for i in xTrackArray:
                s.append([i, fun(i)])
        return {"trackArray": np.array(s), "P": w}


def gen(start, end, numberList):
    # dataList = json.load(open('./gj.json', encoding='utf-8'))
    # data = []
    # start =5490
    # for i in range(start, start +50):
    #     data.append([dataList[i]['x'], dataList[i]['y']])

    # 生成一段轨迹 然后让ai修改
    bzr = bezierTrajectory()
    # 生成100，200点到600，700的轨迹 点的个数为110个
    hh = bzr.trackArray(start, end, numberList, 6, 3, 0.4)
    data = hh['trackArray'].tolist()
    # 交给模型去修改为更符合人的轨迹
    out = getGj(data)
    return out


device = torch.device('cpu')
gjsett = {"x": 1118, "y": 715}
mod = torch.load('./modelyzm.pth')


def getGj(data):
    data = data.copy()
    cd = len(data)
    # data += [[0,0]]*(maxNum-cd)
    data = np.array(data, dtype=np.double)
    mx = np.min(data[:, 0])
    my = np.min(data[:, 1])
    data[:cd, 0] = ((data[:cd, 0] - mx) / gjsett['x'])
    data[:cd, 1] = ((data[:cd, 1] - my) / gjsett['y'])
    dm = data.tolist()

    d = torch.tensor(dm, dtype=torch.float32).to(device).unsqueeze(0)
    st = 1
    buc = 2
    step = d.shape[1] // buc

    for _ in range(d.shape[1] // step):
        d[:, st:(st + step), :] = 0
        st = st + step + 1
        if st + step >= d.shape[1]:
            break
    if d.shape[1] // step <= d.shape[1] / step:
        d[:, st:-1, :] = 0

    outx, outy = mod(d)
    outx = outx.squeeze(0)
    outy = outy.squeeze(0)
    outx = outx.tolist()
    outy = outy.tolist()
    outdata = []

    for i in range(len(outx)):
        if i == 0:
            outdata.append([dm[0][0] * gjsett['x'] + mx, dm[0][1] * gjsett['y'] + my])
            continue
        if i == len(outx) - 1:
            outdata.append([dm[i][0] * gjsett['x'] + mx, dm[i][1] * gjsett['y'] + my])
            continue
        outdata.append([outx[i] * gjsett['x'] + mx, outy[i] * gjsett['y'] + my])
        if len(outdata) == cd:
            return outdata

    return outdata

# --------->

def drag_element_in_frame(frame, element, path):
    ac = Actions(frame)
    ac.move_to(element)

    # Start the drag
    ac.hold()

    # Follow the provided path
    pre_x = 0
    pre_y = 0
    for x, y in path:
        ac.move(x - pre_x, y - pre_y, 0.2)
        pre_x, pre_y = x, y

    # Release the drag
    ac.release()


logger.info('id={}, 出现滑块'.format(self.uuid))
frame_locator = self.page.get_frame("#baxia-dialog-content")
element_selector = "#nc_1_n1z"
traceList = gen([0, 0], [350, 5], 30)
drag_element_in_frame(frame_locator, element_selector, traceList)
time.sleep(2)
self.page.goto("https://www.amap.com/")